home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / BG_SRC.ZIP / BG_EVAL.C < prev    next >
C/C++ Source or Header  |  1995-03-26  |  23KB  |  768 lines

  1. /*
  2.  *    B G _ E V A L . C  -- this file deals with evaulating the 'goodness'
  3.  *        of a backgammon situation by looking at the layouts and working
  4.  *        out various values based on characteristics of the layouts. The
  5.  *        weighted sum of these values is the 'goodness' of a particular
  6.  *        layout for a particular player.
  7.  *
  8.  *     O.F.Ransen, 14th May 1994
  9.  */
  10.  
  11. #include <stdlib.h>
  12. #include <stdio.h>
  13. #include <string.h>
  14. #include <conio.h>
  15. #include "bg.h"
  16.  
  17. /*************************************************************************/
  18.  
  19. /***** Functions which look at particulars of the current situation *****/
  20. /***** All of these functions should return a number 0..100 *************/
  21. static long  Runners_Score (Layout_t Me, Layout_t Him) ;
  22. static long  Safety_Score (Layout_t Me, Layout_t Him) ;
  23. static long  Tense_Aggro_Score (Layout_t Me, Layout_t Him) ;
  24. static long  Wall_Score (Layout_t Me, Layout_t Him) ;
  25. static long  Inner_Sec_Score (Layout_t Me, Layout_t Him) ;
  26. static long  Outer_Sec_Score (Layout_t Me, Layout_t Him) ;
  27. static long  Run_Sec_Score (Layout_t Me, Layout_t Him) ;
  28. static long  Mid_Sec_Score (Layout_t Me, Layout_t Him) ;
  29. static long  Agro_Coward_Score (Layout_t Me, Layout_t Him) ;
  30. static long  Prime_Score (Layout_t Me, Layout_t Him);
  31. static long  Entering_IT_Score (Layout_t Me) ;
  32. static long  Exiting_Score (Layout_t Me, Layout_t Him) ;
  33. static short Get_Probs (Layout_t Me, Layout_t Him, short My_Pnt) ;
  34. static short Get_Hit_Prob (Layout_t Me, Layout_t Him, short My_Pnt, Dice_t* Dc) ;
  35. static long  Constructor_Score (Layout_t Me, Layout_t Him) ;
  36.  
  37. /*************************************************************************/
  38.  
  39. static long Runners_Score (Layout_t Me, Layout_t Him)
  40. /*
  41. PURPOSE: To return a value based on my last piece.
  42. */
  43. {
  44.     long p,Score  ;
  45.  
  46.     p = 0 ;
  47.     while ((Me[p] == 0) && (p < HOME_I)) {
  48.         p++ ;
  49.     }
  50.  
  51.     Score = (p*100)/(N_PLACES-1) ;
  52.  
  53.     return (Score) ;
  54. }
  55.  
  56. /*************************************************************************/
  57.  
  58. static long Safety_Score (Layout_t Me, Layout_t Him)
  59. /*
  60. PURPOSE: To return a value showing how 'safe' the situation is.
  61. NOTES:   1) If he has more than one piece on the bar and I have no uncovered
  62.          pieces in my inner table then I am 100% safe.
  63.          2) If he has at least one piece on the bar and I have a 6 piece
  64.          wall in my inner table then I am 100% safe.
  65.          3) If there is no overlap then I am 100% safe.
  66. */
  67. {
  68.     #define TREMBLE 4  /* Start to get scared when prob >= (TREMBLE/36) */
  69.     short p ;
  70.     long Uncovered,Score ;
  71.  
  72.     if ((Him[BAR_I] > 1) && (Inner_Sec_Score(Me,Him) == 100l)) {
  73.         Score = 100l ;
  74.     } else if ((Him[BAR_I] > 0) && (Wall_Score (Me,Him) == 100l)) {
  75.         Score = 100l ;
  76.     } else if (!Overlap(Me,Him)) {
  77.         Score = 100l ;
  78.     } else {
  79.         /* Rather more complicated... */
  80.         Uncovered = 0 ;
  81.         for (p = POINT1_I ; p <= POINT24_I ; p++) {
  82.             if (Me[p] == 1) {
  83.                 if (Get_Probs (Me,Him,p) >= TREMBLE) {
  84.                     Uncovered++ ;
  85.                 }
  86.             }
  87.         }
  88.         if (Uncovered > (long)MAX_MOVES) {
  89.             Uncovered = (long)MAX_MOVES ;
  90.         }
  91.         Score= (long)((((long)MAX_MOVES-Uncovered)*100)/(long)MAX_MOVES) ;
  92.     }
  93.  
  94.     return (Score) ;
  95. }
  96.  
  97. /*************************************************************************/
  98. #if DRODBAR
  99. long Weighted_Safety (Layout_t Me, Layout_t Him)
  100. /*
  101. PURPOSE: To return a score based on the 'safeness' of the exposed
  102. pieces. We look at each single piece and calculate the probabilty
  103. that it will be hit by the next throw of the opponents dice. We
  104. add the probablilities up and return a number based on that.
  105. */
  106. {
  107.     long Total = 0, Prob ;
  108.     short p ;
  109.  
  110.     /* For every uncovered point... */
  111.     for (p = 1 ; p < HOME_I ; p++) {
  112.         if (Me[p] == 1) {
  113.             Prob  = (long)Get_Probs (Me,Him,p,TRUE) ;
  114.             Total = Total + Prob ;
  115.         }
  116.     }
  117.     return (Total) ;
  118. }
  119. #endif
  120. /*************************************************************************/
  121.  
  122. static long Tense_Aggro_Score (Layout_t Me, Layout_t Him)
  123. /*
  124. PURPOSE: To balance the number of pieces I have eaten with the number
  125.          of exposed pieces in his inner table. The score is high when
  126.          I eat a lot and he has lots of exposed pieces.
  127. */
  128. {
  129.     const long Max_Exposed = 6 ;
  130.     const long Max_Eaten   = 4 ;
  131.  
  132.     long Exposed, Eaten, Score ;
  133.     short p;
  134.  
  135.     Exposed = 0 ;
  136.     for (p = 19 ; p <= 24 ; p++) {
  137.         if (Him[p] == 1) {
  138.             Exposed++ ;
  139.         }
  140.     }
  141.  
  142.     Eaten = Him[BAR_I] ;
  143.  
  144.     Score = ((Exposed*100)/Max_Exposed) * ((Eaten*100)/Max_Eaten) ;
  145.     return (Score/100) ;
  146. }
  147.  
  148. /*************************************************************************/
  149.  
  150. long Aggression_Score (Layout_t Me, Layout_t Him)
  151. /*
  152. PURPOSE: To return a value showing how many pieces have been eaten by me.
  153. NOTES:   1) Used in this file, but also in BG_FACE.C to draw the teeth!
  154. */
  155. {
  156.     long Eaten ;
  157.  
  158.     Eaten = Him[BAR_I] ;
  159.     if (Eaten > (long)MAX_MOVES) { /* Rare, so limit it's importance */
  160.         Eaten = (long)MAX_MOVES ;
  161.     }
  162.     return ((Eaten*100l)/(long)MAX_MOVES) ;
  163. }
  164.  
  165. /*************************************************************************/
  166.  
  167. static long Wall_Score (Layout_t Me, Layout_t Him)
  168. /*
  169. PURPOSE: To return a score based on how much of a wall I have built in
  170. */
  171. {
  172.     const short Max_Wall_Score = 6 ;
  173.     long Score ;
  174.     short p ;
  175.  
  176.     Score = 0 ;
  177.     for (p = 19 ; p <= POINT24_I ; p++) {
  178.         if (Me[p] > 1) {
  179.             Score++ ;
  180.         }
  181.     }
  182.     return ((Score*100)/Max_Wall_Score) ;
  183. }
  184.  
  185. /*************************************************************************/
  186.  
  187. static long Inner_Sec_Score (Layout_t Me, Layout_t Him)
  188. /*
  189. PURPOSE: To return a score based on how few of my pieces are
  190.          uncovered in my inner table.
  191. */
  192. {
  193.     long const Max_Uncovered = 6 ;
  194.     long Uncovered ;
  195.     short p ;
  196.  
  197.     Uncovered = 0 ;
  198.     for (p = 19 ; p <= 24 ; p++) {
  199.         if (Me[p] == 1) {
  200.             Uncovered++ ;
  201.         }
  202.     }
  203.     return (((Max_Uncovered-Uncovered)*100)/Max_Uncovered) ;
  204. }
  205.  
  206. /*************************************************************************/
  207.  
  208. static long Outer_Sec_Score (Layout_t Me, Layout_t Him)
  209. /*
  210. PURPOSE: To return a score based on how few pieces are uncovered
  211.          in my outer table.
  212. */
  213. {
  214.     long const Max_Uncovered = 6 ;
  215.     long Uncovered ;
  216.     short p ;
  217.  
  218.     Uncovered = 0 ;
  219.     for (p = 13 ; p <= 18 ; p++) {
  220.         if (Me[p] == 1) {
  221.             Uncovered++ ;
  222.         }
  223.     }
  224.     return (((Max_Uncovered-Uncovered)*100)/Max_Uncovered) ;
  225. }
  226.  
  227. /*************************************************************************/
  228.  
  229. static long Run_Sec_Score (Layout_t Me, Layout_t Him)
  230. /*
  231. PURPOSE: To return a score based on how few of my pieces are uncovered
  232.          in his inner table.
  233. */
  234. {
  235.     long const Max_Uncovered = 6 ;
  236.     long Uncovered ;
  237.     short p ;
  238.  
  239.     Uncovered = 0 ;
  240.     for (p = 1 ; p <= 6 ; p++) {
  241.         if (Me[p] == 1) {
  242.             Uncovered++ ;
  243.         }
  244.     }
  245.     return (((Max_Uncovered-Uncovered)*100)/Max_Uncovered) ;
  246. }
  247.  
  248. /*************************************************************************/
  249.  
  250. static long Mid_Sec_Score (Layout_t Me, Layout_t Him)
  251. /*
  252. PURPOSE: To return a score based on how few of my pieces are uncovered
  253.          in his outer table.
  254. */
  255. {
  256.     long const Max_Uncovered = 6 ;
  257.     long Uncovered ;
  258.     short p ;
  259.  
  260.     Uncovered = 0 ;
  261.     for (p = 7 ; p <= 12 ; p++) {
  262.         if (Me[p] == 1) {
  263.             Uncovered++ ;
  264.         }
  265.     }
  266.     return (((Max_Uncovered-Uncovered)*100)/Max_Uncovered) ;
  267. }
  268.  
  269. /*************************************************************************/
  270.  
  271. static long Agro_Coward_Score (Layout_t Me, Layout_t Him)
  272. /*
  273. PURPOSE: To return a score based on how many I can eat without risk.
  274. */
  275. {
  276.     short p ;
  277.     for (p = 19 ; p <= POINT24_I ; p++) {
  278.         if (Me[p] == 1) {
  279.             return (0) ;
  280.         }
  281.     }
  282.     /* No uncovered pieces in home area, I can eat */
  283.     return (Aggression_Score(Me,Him)) ;
  284. }
  285.  
  286. /*************************************************************************/
  287.  
  288. static long Prime_Score (Layout_t Me, Layout_t Him)
  289. /*
  290. PURPOSE: To return a score based on the longest run of occupied points
  291. */
  292. {
  293.     #define MAX_PRIME 6
  294.     long P_Count,Max_Found ;
  295.     short p ;
  296.  
  297.     if (!Overlap (Me,Him)) {
  298.         return (0l) ;
  299.     }
  300.  
  301.     P_Count = 0 ;
  302.     Max_Found = 0 ;
  303.     for (p = 15 ; p < 22 ; p++) {
  304.         if (Me[p] > 1) {
  305.             P_Count++ ;
  306.             if (P_Count > Max_Found) {
  307.                 Max_Found = P_Count ;
  308.             }
  309.         } else {
  310.             P_Count=0 ;
  311.         }
  312.     }
  313.     if (Max_Found >= MAX_PRIME) {
  314.         return (100l) ;
  315.     } else {
  316.         return ((Max_Found*100l)/MAX_PRIME) ;
  317.     }
  318. }
  319.  
  320. /*************************************************************************/
  321.  
  322. #define MAX_ENTERING_SCORE 49  /* These two defines force exiting... */
  323. #define MIN_EXITING_SCORE  51  /* ...to always win over entering...  */
  324.  
  325. static long Entering_IT_Score (Layout_t Me)
  326. /*
  327. PURPOSE: To return a value based on getting into my inner table.
  328. NOTES:  1) This is rather hand-crafted...
  329. */
  330. {
  331.     #define FIRST_IT_POINT   19  /* Just inside the bar */
  332.     #define MAX_END_PIECES    1
  333.  
  334.     long p,Score,N_End_Pieces ;
  335.  
  336.     p = BAR_I ;
  337.     while ((Me[p] == 0) && (p < FIRST_IT_POINT)) {
  338.         p++ ;
  339.     }
  340.  
  341.     if (p >= FIRST_IT_POINT) {
  342.         Error_Exit ("Entering score when bearing off!") ;
  343.     }
  344.  
  345.     N_End_Pieces = Me[p] ;
  346.     if (N_End_Pieces > 1) {
  347.         /*
  348.          * There is a column to be shifted, return a very low score
  349.          */
  350.         if (N_End_Pieces > MAX_END_PIECES) {
  351.             N_End_Pieces = MAX_END_PIECES ;
  352.         }
  353.         Score = MAX_END_PIECES - N_End_Pieces ;
  354.     } else {
  355.        /*
  356.         * There is just a single trailing piece
  357.         */
  358.         Score = (p*MAX_ENTERING_SCORE)/(FIRST_IT_POINT-1) ;
  359.     }
  360.  
  361.     return (Score) ;
  362. }
  363.  
  364. /*************************************************************************/
  365.  
  366. static long Exiting_Score (Layout_t Me, Layout_t Him)
  367. /*
  368. PURPOSE: To return a number based how many pieces I have taken off
  369.          the board or how close I have got to taking them off
  370. */
  371. {
  372.     long Score ;
  373.     Score = (Me[HOME_I]*(100l-MIN_EXITING_SCORE))/(long)N_PIECES ;
  374.     Score = Score + MIN_EXITING_SCORE ;
  375.     return (Score);
  376. }
  377.  
  378. /*************************************************************************/
  379.  
  380. static short Get_Probs (Layout_t Me, Layout_t Him, short My_Point)
  381. /*
  382. PURPOSE: To return a number (0..36 inclusive) which gives the
  383. probability that the point will be hit by the opponent.
  384. */
  385. {
  386.     Dice_t Dice ;
  387.     short Total,d0,d1,i,Loc_Tot ;
  388.  
  389.     Total = 0 ;
  390.  
  391.     for (d0 = 1 ; d0 <= 6 ; d0++) {
  392.         for (d1 = 1 ; d1 <= 6 ; d1++) {
  393.             if (d1 == d0) {
  394.                 Dice.N_Vals = 4 ;
  395.                 for (i = 0 ; i < 4 ; i++) {
  396.                     Dice.Values[i] = (char)d0 ;
  397.                 }
  398.             } else {
  399.                 Dice.N_Vals = 2 ;
  400.                 Dice.Values[0] = (char)d0 ;
  401.                 Dice.Values[1] = (char)d1 ;
  402.             }
  403.             Loc_Tot = Get_Hit_Prob (Me,Him,My_Point,&Dice) ;
  404.             Total   = Total + Loc_Tot ;
  405.         }
  406.     }
  407.  
  408.     return (Total) ;
  409. }
  410.  
  411. /*************************************************************************/
  412.  
  413. static short Get_Hit_Prob (Layout_t Me, Layout_t Him, short My_Point, Dice_t* Dice)
  414. /*
  415. PURPOSE: To return 0 if the piece cannot be hit with the Dice, or
  416.          1 if it can be hit.
  417. */
  418. {
  419.     short His_Point,His_Start,Mine,i,d0,d1 ;
  420.     short Long_Point,Mediate_Point0,Mediate_Point1 ;
  421.  
  422.     if (Me[My_Point] != 1) {
  423.         return (0) ;
  424.     }
  425.  
  426.     His_Point = Reverse_Index (My_Point) ;
  427.     d0 = Dice->Values[0] ;
  428.     d1 = Dice->Values[1] ;
  429.  
  430.     if (Dice->N_Vals == 4) {
  431.         /* Hit via double */
  432.         for (i = 1 ; i <= 4 ; i++) {
  433.             His_Start = His_Point - (d0*i) ; /* Where he starts from */
  434.             Mine      = Reverse_Index (His_Start) ;
  435.             if (His_Start < BAR_I) {
  436.                 return (0) ; /* He can't be at less than the bar point */
  437.             } else if (Me[Mine] > 1) {
  438.                 return (0) ; /* I occupy that point */
  439.             } else if (Him[His_Start] > 0) {
  440.                 return (1) ; /* He could get me with that piece */
  441.             }
  442.         }
  443.         return (0) ;
  444.     } else {
  445.         /* Check for direct hit with first dice... */
  446.         His_Start = His_Point - d0 ;
  447.         if (His_Start >= BAR_I) {
  448.             if (Him[His_Start] > 0) {
  449.                 return (1) ;
  450.             }
  451.         }
  452.  
  453.         /* Check for direct hit with second dice... */
  454.         His_Start = His_Point - d1 ;
  455.         if (His_Start >= BAR_I) {
  456.             if (Him[His_Point-d1] > 0) {
  457.                 return (1) ;
  458.             }
  459.         }
  460.  
  461.         /* Check for an indirect hit... */
  462.         Long_Point = His_Point - (d0 + d1) ;
  463.         if (Long_Point < BAR_I) {
  464.             return (0) ;
  465.         } else if (Him[Long_Point] == 0) {
  466.             return (0) ;
  467.         } else {
  468.             Mediate_Point0 = Reverse_Index (His_Point - d0) ;
  469.             Mediate_Point1 = Reverse_Index (His_Point - d1) ;
  470.             if ((Me[Mediate_Point0] > 1) && (Me[Mediate_Point1] > 1)) {
  471.                 return (0) ; /* I block indirect hit */
  472.             } else {
  473.                 return (1) ; /* No blockage */
  474.             }
  475.         }
  476.     }
  477. }
  478.  
  479. /*************************************************************************/
  480.  
  481. boolean Overlap (Layout_t Me, Layout_t Him)
  482. /*
  483. PURPOSE: To return TRUE if there are any of his pieces in front of any
  484.          of mine.
  485. */
  486. {
  487.     short p, My_Last ;
  488.  
  489.     My_Last = HOME_I ; /* Optimistic */
  490.     for (p = HOME_I ; p >= BAR_I ; p--) {
  491.         if (Me[p] != 0) {
  492.             My_Last = p ;
  493.         }
  494.     }
  495.  
  496.     p = Reverse_Index (My_Last) ;
  497.     while (p >= BAR_I) {
  498.         if (Him[p] != 0) {
  499.             return (TRUE) ;
  500.         }
  501.         p-- ;
  502.     }
  503.  
  504.     return (FALSE) ;
  505. }
  506.  
  507. /***************************************************************************/
  508.  
  509. short Pip_Count (Layout_t Layout)
  510. /*
  511. PURPOSE: To return the pip count of this layout
  512. NOTES:   Smaller numbers are better, means less pieces far away.
  513. */
  514. {
  515.     short p,P_Count ;
  516.  
  517.     P_Count = 0 ;
  518.     for (p = BAR_I ; p <= HOME_I ; p++) {
  519.     P_Count = P_Count + ((HOME_I-p)*Layout[p]) ;
  520.     }
  521.  
  522.     if (P_Count < 0) {
  523.         Error_Exit ("P_Count < 0") ;
  524.     }
  525.  
  526.     return (P_Count) ;
  527. }
  528.  
  529. /*************************************************************************/
  530.  
  531. short Pip_Count_Diff (Layout_t Me, Layout_t Him)
  532. /*
  533. PURPOSE: To return a number showing the 'advantage' one player has over
  534.      the other. If the number is negative He has the advantage, if
  535.      the number is positive I have the advantage.
  536. */
  537. {
  538.     short Mine,His ;
  539.  
  540.     Mine = Pip_Count (Me) ;
  541.     His  = Pip_Count (Him) ;
  542.  
  543.     return (His - Mine) ;
  544. }
  545.  
  546. /*************************************************************************/
  547.  
  548. long Pip_Count_Score (Layout_t Me, Layout_t Him)
  549. /*
  550. PURPOSE: To return a score based on the pip count.
  551. */
  552. {
  553.     const long Worst_Pips = -375l ;
  554.     const long Pips_Range = (375l*2l) ;
  555.     long  Pips,Score ;
  556.  
  557.     Pips  = (long)Pip_Count_Diff (Me,Him) ;
  558.     Score = ((Pips - Worst_Pips)*100l)/Pips_Range ;
  559.  
  560.     return (Score) ;
  561. }
  562.  
  563. /*************************************************************************/
  564.  
  565. short Total_Pieces_On_Board (Layout_t Me, Layout_t Him)
  566. /*
  567. PURPOSE: To return the number of pieces left on the board.
  568. */
  569. {
  570.     short Mine,His ;
  571.  
  572.     Mine = Pieces_On_Board (Me) ;
  573.     His  = Pieces_On_Board (Him) ;
  574.  
  575.     return (Mine + His) ;
  576. }
  577.  
  578. /*************************************************************************/
  579.  
  580. short Pieces_On_Board (Layout_t Layout)
  581. /*
  582. PURPOSE: To return the number of pieces left on the board in My layout
  583. */
  584. {
  585.     short Pieces ;
  586.  
  587.     Pieces = 15 - Layout[HOME_I] ;
  588.  
  589.     return (Pieces) ;
  590. }
  591.  
  592. /*************************************************************************/
  593.  
  594. static long Constructor_Score (Layout_t Me, Layout_t Him)
  595. /*
  596. PURPOSE: To return a score based on the number of constructors in
  597.          my outer table.
  598. */
  599. {
  600.     #define QUARTER 9  /* 9/36 = a quarter no? */
  601.     long Count,Danger ;
  602.     short p ;
  603.  
  604.     /*
  605.      * See if we have the basis for construction...
  606.      */
  607.     if (Me[19] < 3) {
  608.         return (0l) ;
  609.     }
  610.     if (!((Me[18] > 2) || (Me[17] > 2))) {
  611.         return (0l) ;
  612.     }
  613.  
  614.     /*
  615.      * If we get here we have a fullish bar point and a fattish
  616.      * pre-bar point too. Now see how many single constructors
  617.      * there are...
  618.      */
  619.     Count = 0 ;
  620.     Danger = 0 ;
  621.     for (p = 14 ; p <= 16 ; p++) {
  622.         if (Me[p] == 1) {
  623.             Danger = Danger + Get_Probs (Me,Him,p) ;
  624.             Count++ ;
  625.         }
  626.     }
  627.     if (Count > 0) {
  628.         if ((Danger/Count) > QUARTER) {
  629.             Count = 0 ;
  630.         }
  631.     }
  632.  
  633.     return ((Count*100l)/3l) ;
  634. }
  635.  
  636. /*************************************************************************/
  637.  
  638. /* The W_Func_t, holds the function, the name of the function (in
  639. many languages), and the weight for the function for both players. */
  640.  
  641. typedef struct {
  642.     long (*W_Func)(Layout_t,Layout_t) ;  /* Type of function */
  643.     long Weight [N_PLAYERS] ;            /* Weights for each player */
  644.     long Min,Max ;                       /* For later analysis */
  645.     char Name [32] ;                     /* For later analysis */
  646. } W_Func_t ;
  647.  
  648. static W_Func_t W_F_Table [N_WEIGHTS] = {
  649.     /* Function,        weight  min  max  id  */
  650.     {Runners_Score,     {0,0},  200,-200,"Runners     " },
  651.     {Prime_Score,       {0,0},  200,-200,"Prime       " },
  652.     {Safety_Score,      {0,0},  200,-200,"Safety      " },
  653.     {Aggression_Score,  {0,0},  200,-200,"Aggro       " },
  654.     {Tense_Aggro_Score, {0,0},  200,-200,"Tense Aggro " },
  655.     {Wall_Score,        {0,0},  200,-200,"Wall        " },
  656.     {Agro_Coward_Score, {0,0},  200,-200,"Agro Coward " },
  657.     {Inner_Sec_Score,   {0,0},  200,-200,"Inr Sec     " },
  658.     {Outer_Sec_Score,   {0,0},  200,-200,"Outr Sec    " },
  659.     {Run_Sec_Score,     {0,0},  200,-200,"Run Sec     " },
  660.     {Mid_Sec_Score,     {0,0},  200,-200,"Mid Sec     " },
  661.     {Pip_Count_Score,   {0,0},  200,-200,"Pip Score   " },
  662.     {Constructor_Score, {0,0},  200,-200,"Constructor " }
  663. } ;
  664.  
  665. /*************************************************************************/
  666. /* See BG_USER1.C and BG.H for names of opponents                        */
  667. long Weights [N_OPPS][N_WEIGHTS] = {
  668.  /*runrs  pri  safe  aggro tenagr wall agrwal innr outr runsec midsec pips cons */
  669. {   73,   0,  23,  50,  79,  35,  50, 100,  25,  60,  75,  75,  16}, // Sergio
  670. {   36,  50,  24,  76,  48,  20,  44,  46,  50,  40,   5,  64,  58}, // Enzo
  671. {   58,  10,  38,  85,  54,  70,  45,  70,  70,  35,  70,  60,   0}, // Owen
  672. {   51,  65,  59,  51,  10,  25,  10,  51,  90,  35,  15,  69,  10}, // Brian
  673. } ;
  674.  
  675. static short Curr_Opponent = SERGIO ;
  676.  
  677. void Setup_Weights (short New_Opponent, Player_t Player)
  678. /*
  679. PURPOSE: To copy the opponents weights into the W_F_Table.
  680.          The Player will be black or white, and we must copy
  681.          the opponents weights into the black or white list
  682.          of weights. The list of weights of the human (white or
  683.          black) are set to 0 to speed up evaluation.
  684. */
  685. {
  686.     short w ;
  687.     for (w = 0 ; w < N_WEIGHTS ; w++) {
  688.         W_F_Table[w].Weight[Player] = Weights[New_Opponent][w] ;
  689.         W_F_Table[w].Weight[OPPONENT(Player)] = 0 ;
  690.     }
  691.     if (Curr_Opponent != New_Opponent) {
  692.         Init_Stats () ;
  693.         Curr_Opponent = New_Opponent ;
  694.     }
  695. }
  696.  
  697. /*************************************************************************/
  698.  
  699. static short Curr_Black_Id = SERGIO ;
  700. static short Curr_White_Id = ENZO ;
  701.  
  702. void Init_Genetic_Opponents (short Black, short White)
  703. /*
  704. PURPOSE: To set the black players weights to the values in
  705. Weights[BLACK], and the white players weights to the values in
  706. Weights[WHITE].
  707. */
  708. {
  709.     short w ;
  710.     for (w = 0 ; w < N_WEIGHTS ; w++) {
  711.         W_F_Table[w].Weight[BLACK_PLAYER] = Weights[Black][w] ;
  712.         W_F_Table[w].Weight[WHITE_PLAYER] = Weights[White][w] ;
  713.     }
  714.     Curr_Black_Id = Black ;
  715.     Curr_White_Id = White ;
  716. }
  717.  
  718. /*************************************************************************/
  719.  
  720. long Evaluate_Move (Layout_t Me, Layout_t Him, Player_t Player)
  721. /*
  722. PURPOSE: To return the weighted sum for this player and his situation.
  723. */
  724. {
  725.     long Score,Temp ;
  726.     extern boolean Debugging,Genetics ;
  727.     ushort w ;
  728.  
  729.     if (!Overlap(Me,Him)) {
  730.         /* The choice of move is rather simple, we are just racing */
  731.         if (!Bearing_Off(Me)) {
  732.             Score = Entering_IT_Score (Me) ; /* Move closer to inner table */
  733.         } else {
  734.             Score = Exiting_Score (Me,Him) ; /* Take pieces off inner table */
  735.         }
  736.         return (Score) ;
  737.     }
  738.  
  739.     // Using normal statistics methods, not the NN brain
  740.     Score = 0 ;
  741.     for (w = 0 ; w < N_WEIGHTS ; w++) {
  742.         /* Get the value for this weight */
  743.         Temp  = (*W_F_Table[w].W_Func) (Me,Him) ;
  744.         /* Check the value is not illegal */
  745.         if (Temp < 0) {
  746.             printf ("\nAn evaluation score = %ld, w=%d, <%s>.",Temp,w,W_F_Table[w].Name) ;
  747.             Error_Exit ("A negative evaluation score") ;
  748.         } else if (Temp > 100) {
  749.             printf ("\nAn evaluation score = %ld, w=%d,<%s>.",Temp,w,W_F_Table[w].Name) ;
  750.             Error_Exit ("An evaluation greater than 100") ;
  751.         }
  752.         /* Record the excursions of the weight for later analysis */
  753.         if (Temp > W_F_Table[w].Max) {
  754.             W_F_Table[w].Max = Temp ;
  755.         }
  756.         if (Temp < W_F_Table[w].Min) {
  757.             W_F_Table[w].Min = Temp ;
  758.         }
  759.         /* Add the value into the score */
  760.         Score = Score + (W_F_Table[w].Weight[Player]*Temp) ;
  761.     }
  762.  
  763.     return (Score) ;
  764. }
  765.  
  766. /*************************************************************************/
  767.  
  768.